version: 2.1

global_context: &global_context
  context:
    - org-global

global_remote_docker: &global_remote_docker
  setup_remote_docker:
    docker_layer_caching: true

global_dockerhub_auth: &global_dockerhub_auth
  auth:
    username: $GLOBAL_DOCKERHUB_USERNAME
    password: $GLOBAL_DOCKERHUB_PASSWORD

defaults: &defaults
  docker:
    - image: deliveroo/circleci:1.7
      <<: *global_dockerhub_auth

import_image: &import_image
  name: Import Docker image
  command: |
    set -ex
    docker load --input "workspace/${CIRCLE_PROJECT_REPONAME}-${CIRCLE_SHA1}.tar"

executors:
  ubuntu:
    machine:
      image: ubuntu-2204:2023.02.1
    resource_class: small

jobs:
  build:
    <<: *defaults
    steps:
      - *global_remote_docker
      - checkout
      - run:
          name: Build CI Image
          command: |
            docker build -f Dockerfile -t $(./image) .
      - run:
          name: Save CI Image
          command: |
            mkdir -p workspace
            docker save $(./image) \
                --output "workspace/${CIRCLE_PROJECT_REPONAME}-${CIRCLE_SHA1}.tar"
      - persist_to_workspace:
          root: workspace
          paths:
            - "*.tar"

  test:
    executor: ubuntu
    steps:
      - checkout
      - run:
          name: tests
          # Had to run in the background to ensure the health check continue forever
          command: bats tests/*.bats

  push_master:
    parameters:
      publish_to_docker_hub:
        type: boolean
        default: false
    <<: *defaults
    steps:
      - when:
          condition:
            equal: [ false, << parameters.publish_to_docker_hub >> ]
          steps:
            - run:
                name: Publish to Docker Hub decision
                command: |
                  echo "Not publishing to Docker Hub or incrementing the GitHub tags.\n\nSet the publish_to_docker_hub value to \"true\" if you want to publish."
            - run: circleci-agent step halt
      - add_ssh_keys:
          fingerprints:
            - a7:2f:cb:c2:b3:6a:17:c4:8f:3a:8d:77:57:d3:41:bb
      - *global_remote_docker
      - checkout
      - attach_workspace:
          at: workspace
      - run:
          <<: *import_image
      - run:
          name: Tag the git commit
          command: |
            # This fails if the tag already exists
            # preventing a push to the docker hub.
            git tag "$(cat VERSION)"
            git push --tags
      - run:
          name: Add Latest Tag
          command: docker tag $(./image) "${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}:latest"
      - run:
          name: Push Latest and Version image tags
          command: |
            DOCKER_USER="${GLOBAL_DOCKERHUB_USERNAME}" DOCKER_PASS="${GLOBAL_DOCKERHUB_PASSWORD}" push_image_to_docker_hub \
            "$(./image)" "${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}:latest"

  push_staging:
    <<: *defaults
    steps:
      - add_ssh_keys:
          fingerprints:
            - a7:2f:cb:c2:b3:6a:17:c4:8f:3a:8d:77:57:d3:41:bb
      - *global_remote_docker
      - checkout
      - attach_workspace:
          at: workspace
      - run:
          <<: *import_image
      - run:
          name: Tag the Docker image
          command: docker tag $(./image) "${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}:staging"
      - run:
          name: Push the image
          command: docker push "${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}:staging"



master_only: &master_only
  filters:
    branches:
      only:
        - master
staging_only: &staging_only
  filters:
    branches:
      only:
        - staging

workflows:
  build_test_publish:
    jobs:
      - build:
          <<: *global_context
      - test:
          <<: *global_context
          requires:
            - build
      - push_master:
          <<: *master_only
          publish_to_docker_hub: true
          requires:
            - build
            - test
          <<: *global_context
      - push_staging:
          <<: *staging_only
          requires:
            - build
            - test
          <<: *global_context
